package com.loren.demo13.data_permission;

import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.ItemsList;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.PlainSelect;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
public class CustomDataPermissionHandler {

    public Expression getSqlSegment(PlainSelect plainSelect, String whereSegment) {
        Expression where = plainSelect.getWhere();
        if (where == null) {
            return null;
        }
        DataPermission dataPermission = this.getDataPermission(whereSegment);
        if (dataPermission == null) {
            return where;
        }
        String alias = this.getAlias(plainSelect);

        // 根据登录信息获取所属数据权限范围
        DataScope dataScope = DataScope.getRandomDataScope();

        log.info("alias = {}, dataScope = {}", alias, dataScope);

        if (dataScope == DataScope.SELF) {
            EqualsTo equalsTo = new EqualsTo();
            equalsTo.setLeftExpression(this.buildColumn(alias, "create_by"));
            equalsTo.setRightExpression(new LongValue(2));
            return new AndExpression(where, equalsTo);
        } else if (dataScope == DataScope.DEPT) {
            List<Integer> deptIds = Arrays.asList(1, 2);
            ItemsList itemsList = new ExpressionList(deptIds.stream().map(LongValue::new).collect(Collectors.toList()));
            InExpression inExpression = new InExpression(this.buildColumn(alias, "create_dept"), itemsList);
            return new AndExpression(where, inExpression);
        } else if (dataScope == DataScope.ALL) {
            return where;
        }
        return where;
    }

    private Expression buildColumn(String alias, String name) {
        if (alias == null || "".equals(alias)) {
            return new Column(name);
        }
        return new Column(alias + "." + name);
    }

    private DataPermission getDataPermission(String whereSegment) {
        String clazz = whereSegment.substring(0, whereSegment.lastIndexOf("."));
        String methodName = whereSegment.substring(whereSegment.lastIndexOf(".") + 1);
        try {
            Method method = this.getMethod(clazz, methodName);
            if (method != null) {
                return method.getAnnotation(DataPermission.class);
            }
        } catch (Exception e) {
            log.error("构建数据权限出错", e);
        }
        return null;
    }

    /**
     * 获取主表别名
     */
    private String getAlias(PlainSelect plainSelect) {
        Table fromItem = (Table) plainSelect.getFromItem();
        return fromItem.getAlias() == null ? "" : fromItem.getAlias().getName();
    }

    private Method getMethod(String clazz, String method) throws ClassNotFoundException {
        Method[] methods = Class.forName(clazz).getMethods();
        for (Method m : methods) {
            if (Objects.equals(m.getName(), method)) {
                return m;
            }
        }
        return null;
    }
}
